home *** CD-ROM | disk | FTP | other *** search
- /*
- * procMisc.c --
- *
- * Misc. routines to get and set process state.
- *
- * Copyright 1986 Regents of the University of California
- * Permission to use, copy, modify, and distribute this
- * software and its documentation for any purpose and without
- * fee is hereby granted, provided that the above copyright
- * notice appear in all copies. The University of California
- * makes no representations about the suitability of this
- * software for any purpose. It is provided "as is" without
- * express or implied warranty.
- */
-
- #ifndef lint
- static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/proc/procMisc.c,v 9.26 92/09/27 15:50:49 shirriff Exp $ SPRITE (Berkeley)";
- #endif /* not lint */
-
- #include <sprite.h>
- #include <proc.h>
- #include <status.h>
- #include <sync.h>
- #include <sched.h>
- #include <sig.h>
- #include <stdlib.h>
- #include <list.h>
- #include <string.h>
- #include <procInt.h>
- #include <rpc.h>
- #include <dbg.h>
- #include <vm.h>
- #include <ctype.h>
- #include <fscache.h>
- #include <fsutil.h>
- #include <rpcClient.h>
- #include <rpcServer.h>
- #include <procServer.h>
- #include <fsrmt.h>
- #include <lfsTypes.h>
- #include <fsconsist.h>
- #include <bstring.h>
- #include <stdio.h>
-
- #define min(a,b) ((a) < (b) ? (a) : (b))
- /*
- * Procedures internal to this file
- */
-
- static ReturnStatus GetRemotePCB _ARGS_((int hostID, Proc_PID pid,
- Proc_PCBInfo *pcbPtr, char *argString));
- static void FillPCBInfo _ARGS_((Proc_ControlBlock *pcbPtr,
- Proc_PCBInfo *statusInfoPtr));
-
- /*
- *----------------------------------------------------------------------
- *
- * Proc_Init --
- *
- * Called during startup to initialize data structures.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Process table initialized, debug list initialized, locks initialized.
- *
- *----------------------------------------------------------------------
- */
-
- void
- Proc_Init()
- {
- ProcInitTable();
- ProcDebugInit();
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Proc_GetPCBInfo --
- *
- * Returns the process control blocks for the specified processes
- * on the specified host. If firstPid is equal to PROC_MY_PID
- * and the hostID is PROC_MY_HOSTID, then the PCB for the current
- * process is returned. Otherwise PCBs for all processes in the
- * range firstPid to lastPid on host hostID are returned. Only
- * the index portions of the processIDs for firstPid and lastPid
- * are relevant.
- *
- * Results:
- * SYS_INVALID_ARG - firstPid was < 0, firstPid > lastPid
- * SYS_ARG_NOACCESS - The buffers to store the pcbs in were not
- * accessible.
- * *trueNumBuffers is set to be the actual number of
- * PCBs returned which can be less than the number requested if
- * lastPid - firstPid is greater than the maximum PCBs available.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- /*
- * Macro to fix up ticks for a process control block.
- */
- #define TICKS_TO_TIME(pcbEntry) \
- Timer_TicksToTime(pcbEntry.kernelCpuUsage.ticks, \
- &pcbEntry.kernelCpuUsage.time); \
- Timer_TicksToTime(pcbEntry.userCpuUsage.ticks, \
- &pcbEntry.userCpuUsage.time); \
- Timer_TicksToTime(pcbEntry.childKernelCpuUsage.ticks, \
- &pcbEntry.childKernelCpuUsage.time); \
- Timer_TicksToTime(pcbEntry.childUserCpuUsage.ticks, \
- &pcbEntry.childUserCpuUsage.time);
-
-
- ReturnStatus
- Proc_GetPCBInfo(firstPid, lastPid, hostID, infoSize, bufferPtr,
- argsPtr, trueNumBuffersPtr)
- Proc_PID firstPid; /* First pid to get info for. */
- Proc_PID lastPid; /* Last pid to get info for. */
- int hostID; /* Host ID to get info for. */
- int infoSize; /* Size of structure */
- Address bufferPtr; /* Pointer to buffers. */
- Proc_PCBArgString *argsPtr; /* Pointer to argument strings. */
- int *trueNumBuffersPtr; /* The actual number of buffers
- used.*/
- {
- register Proc_ControlBlock *procPtr = (Proc_ControlBlock *) NIL;
- int i, j;
- char argString[PROC_PCB_ARG_LENGTH];
- Proc_ControlBlock pcbEntry;
- Boolean remote = FALSE;
- Proc_PID processID = firstPid;
- ReturnStatus status = SUCCESS;
- Proc_PCBInfo statusInfo;
- int bytesToCopy;
-
-
- if (firstPid != PROC_MY_PID) {
- firstPid &= PROC_INDEX_MASK;
- lastPid &= PROC_INDEX_MASK;
- if ((firstPid > lastPid) ||
- ((firstPid == PROC_MY_PID) && hostID != PROC_MY_HOSTID)) {
- return(GEN_INVALID_ARG);
- }
- }
- if (bufferPtr == USER_NIL) {
- return (SYS_ARG_NOACCESS);
- }
- if (hostID != PROC_MY_HOSTID &&
- (hostID <= 0 || hostID > NET_NUM_SPRITE_HOSTS)) {
- return(GEN_INVALID_ARG);
- }
-
- bytesToCopy = min(sizeof(Proc_PCBInfo), infoSize);
- /*
- * Determine whether to get process table entries for this machine.
- * Currently, the information for this machine is returned unless
- * another machine is explicitly specified; i.e., migrated processes
- * get information for their current machine rather than their home.
- */
-
- if (hostID == PROC_MY_HOSTID) {
- #ifdef FORWARD_MIGRATED_GET_PCBS
- procPtr = Proc_GetCurrentProc();
- Proc_Lock(procPtr);
- if (procPtr->genFlags & PROC_FOREIGN) {
- hostID = procPtr->peerHostID;
- processID = procPtr->peerHostID;
- remote = TRUE;
- }
- Proc_Unlock(procPtr);
- #endif /* FORWARD_MIGRATED_GET_PCBS */
- } else if (hostID != rpc_SpriteID) {
- remote = TRUE;
- }
-
- if (firstPid == PROC_MY_PID) {
- /*
- * Return PCB for the current process.
- */
- procPtr = Proc_GetCurrentProc();
- if (!remote) {
- bcopy((Address)procPtr, (Address)&pcbEntry,
- sizeof (Proc_ControlBlock));
- TICKS_TO_TIME(pcbEntry);
- FillPCBInfo(&pcbEntry, &statusInfo);
- } else {
- status = GetRemotePCB(hostID, processID, &statusInfo,
- argString);
- if (status != SUCCESS) {
- return(status);
- }
- }
- if (Proc_ByteCopy(FALSE, bytesToCopy,
- (Address)&statusInfo, (Address) bufferPtr) != SUCCESS) {
- return(SYS_ARG_NOACCESS);
- }
- if (argsPtr != (Proc_PCBArgString *) USER_NIL) {
- if (!remote) {
- if (procPtr->argString != (Address) NIL) {
- (void) strncpy(argString, procPtr->argString,
- PROC_PCB_ARG_LENGTH - 1);
- argString[PROC_PCB_ARG_LENGTH - 1] = '\0';
- } else {
- argString[0] = '\0';
- }
- }
- if (Proc_ByteCopy(FALSE, PROC_PCB_ARG_LENGTH, argString,
- (Address) argsPtr) != SUCCESS) {
- return(SYS_ARG_NOACCESS);
- }
- }
- } else {
-
- /*
- * Return PCB for all processes or enough to fill all of
- * the buffers, whichever comes first.
- */
-
-
- for (i = firstPid, j = 0;
- i <= lastPid;
- i++, j++, (Address) bufferPtr += infoSize) {
- if (!remote) {
- if (i >= proc_MaxNumProcesses) {
- break;
- }
- procPtr = Proc_GetPCB(i);
- if (procPtr == (Proc_ControlBlock *) NIL) {
- panic("Proc_GetInfo: procPtr == NIL!\n");
- status = FAILURE;
- break;
- }
- bcopy((Address)procPtr, (Address)&pcbEntry,
- sizeof (Proc_ControlBlock));
-
- TICKS_TO_TIME(pcbEntry);
- FillPCBInfo(&pcbEntry, &statusInfo);
- } else {
- status = GetRemotePCB(hostID, (Proc_PID) i, &statusInfo,
- argString);
- if (status != SUCCESS) {
- /*
- * Break if we hit an error. The typical error condition
- * is to hit an invalid process ID, which happens since
- * we don't know proc_MaxNumProcesses on the other
- * machine. Instead, we convert GEN_INVALID_ARG to
- * SUCCESS and return what we found so far.
- */
- if (status == GEN_INVALID_ARG) {
- status = SUCCESS;
- }
- break;
- }
- }
- if (Proc_ByteCopy(FALSE, bytesToCopy,
- (Address)&statusInfo, (Address) bufferPtr) != SUCCESS) {
- return(SYS_ARG_NOACCESS);
- }
- if (argsPtr != (Proc_PCBArgString *) USER_NIL) {
- if (!remote) {
- if (procPtr->argString != (Address) NIL) {
- (void) strncpy(argString, procPtr->argString,
- PROC_PCB_ARG_LENGTH - 1);
- argString[PROC_PCB_ARG_LENGTH - 1] = '\0';
- } else {
- argString[0] = '\0';
- }
- }
- if (Proc_ByteCopy(FALSE, PROC_PCB_ARG_LENGTH, argString,
- (Address) &(argsPtr[j])) != SUCCESS) {
- return(SYS_ARG_NOACCESS);
- }
- }
- }
-
- if (trueNumBuffersPtr != USER_NIL) {
- if (Proc_ByteCopy(FALSE, sizeof(j), (Address) &j,
- (Address) trueNumBuffersPtr) != SUCCESS) {
- return(SYS_ARG_NOACCESS);
- }
- }
- }
-
- return(status);
- }
-
-
-
- /*
- * Define some constants used to distinguish RPC sub-commands.
- */
- #define GET_PCB 1
- #define GET_SEG_INFO 2
-
- /*
- *----------------------------------------------------------------------
- *
- * GetRemotePCB --
- *
- * Perform an RPC to get a process control block from another host.
- *
- * Results:
- * The return status from the RPC is returned.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- static ReturnStatus
- GetRemotePCB(hostID, pid, pcbPtr, argString)
- int hostID; /* Host to send RPC to. */
- Proc_PID pid; /* index of PCB to obtain. */
- Proc_PCBInfo *pcbPtr; /* Place to return PCB data. */
- char *argString; /* Place to return argument string. */
- {
- Rpc_Storage storage;
- ReturnStatus status;
- int request;
-
- request = GET_PCB;
- storage.requestParamPtr = (Address)&request;
- storage.requestParamSize = sizeof(request);
- storage.requestDataPtr = (Address)&pid;
- storage.requestDataSize = sizeof(Proc_PID);
- storage.replyParamPtr = (Address)pcbPtr;
- storage.replyParamSize = sizeof(Proc_PCBInfo);
- storage.replyDataPtr = (Address)argString;
- storage.replyDataSize = PROC_PCB_ARG_LENGTH;
-
- status = Rpc_Call(hostID, RPC_PROC_GETPCB, &storage);
- if (status == SUCCESS && storage.replyDataSize == 0) {
- argString[0] = '\0';
- }
- return(status);
-
- }
- /*
- *----------------------------------------------------------------------
- *
- * Proc_GetRemoteSegInfo --
- *
- * Perform an RPC to get info for a VM segment control from another host.
- *
- * Results:
- * The return status from the RPC is returned.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- ReturnStatus
- Proc_GetRemoteSegInfo(hostID, segNum, segInfoPtr)
- int hostID; /* Host to send RPC to. */
- int segNum; /* index of segment to obtain. */
- Vm_SegmentInfo *segInfoPtr; /* Place to return segment data. */
- {
- Rpc_Storage storage;
- ReturnStatus status;
- int request;
-
- request = GET_SEG_INFO;
- storage.requestParamPtr = (Address)&request;
- storage.requestParamSize = sizeof(request);
- storage.requestDataPtr = (Address)&segNum;
- storage.requestDataSize = sizeof(int);
- storage.replyParamPtr = (Address)segInfoPtr;
- storage.replyParamSize = sizeof(Vm_SegmentInfo);
- storage.replyDataPtr = (Address)NIL;
- storage.replyDataSize = 0;
-
- status = Rpc_Call(hostID, RPC_PROC_GETPCB, &storage);
- return(status);
-
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * FillPCBInfo --
- *
- * Fills in a Proc_PCBInfo structure from the contents of a
- * control block.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- static void
- FillPCBInfo(pcbPtr, statusInfoPtr)
- Proc_ControlBlock *pcbPtr; /* Ptr to pcb to convert */
- Proc_PCBInfo *statusInfoPtr; /* Structure to fill in */
- {
- int i;
-
- statusInfoPtr->processor = pcbPtr->processor;
- statusInfoPtr->state = pcbPtr->state;
- statusInfoPtr->genFlags = pcbPtr->genFlags;
- statusInfoPtr->processID = pcbPtr->processID;
- statusInfoPtr->parentID = pcbPtr->parentID;
- statusInfoPtr->familyID = pcbPtr->familyID;
- statusInfoPtr->userID = pcbPtr->userID;
- statusInfoPtr->effectiveUserID = pcbPtr->effectiveUserID;
- statusInfoPtr->event = pcbPtr->event;
- statusInfoPtr->billingRate = pcbPtr->billingRate;
- statusInfoPtr->recentUsage = pcbPtr->recentUsage;
- statusInfoPtr->weightedUsage = pcbPtr->weightedUsage;
- statusInfoPtr->unweightedUsage = pcbPtr->unweightedUsage;
- statusInfoPtr->kernelCpuUsage = pcbPtr->kernelCpuUsage.time;
- statusInfoPtr->userCpuUsage = pcbPtr->userCpuUsage.time;
- statusInfoPtr->childKernelCpuUsage = pcbPtr->childKernelCpuUsage.time;
- statusInfoPtr->childUserCpuUsage = pcbPtr->childUserCpuUsage.time;
- statusInfoPtr->numQuantumEnds = pcbPtr->numQuantumEnds;
- statusInfoPtr->numWaitEvents = pcbPtr->numWaitEvents;
- statusInfoPtr->schedQuantumTicks = pcbPtr->schedQuantumTicks;
- for(i = 0; i < VM_NUM_SEGMENTS; i++) {
- if (pcbPtr->vmPtr != (Vm_ProcInfo *) NIL &&
- pcbPtr->vmPtr->segPtrArray[i] != (Vm_Segment *) NIL) {
- statusInfoPtr->vmSegments[i] =
- (Vm_SegmentID) pcbPtr->vmPtr->segPtrArray[i]->segNum;
- } else {
- statusInfoPtr->vmSegments[i] = (Vm_SegmentID) -1;
- }
- }
- statusInfoPtr->sigHoldMask = pcbPtr->sigHoldMask;
- statusInfoPtr->sigPendingMask = pcbPtr->sigPendingMask;
- for(i = 0; i < SIG_NUM_SIGNALS; i++) {
- statusInfoPtr->sigActions[i] = pcbPtr->sigActions[i];
- }
- statusInfoPtr->peerHostID = pcbPtr->peerHostID;
- statusInfoPtr->peerProcessID = pcbPtr->peerProcessID;
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Proc_RpcGetPCB --
- *
- * Stub to handle a remote request for a PCB or Vm_Segment.
- *
- * Results:
- * Status of reply:
- * GEN_INVALID_ARG - index into table of process control blocks is
- * invalid, or segment is invalid.
- * SUCCESS - information is returned.
- *
- * SUCCESS is passed to the caller on this machine.
- *
- * Side effects:
- * Reply is sent.
- *
- *----------------------------------------------------------------------
- */
- /*ARGSUSED*/
- ReturnStatus
- Proc_RpcGetPCB(srvToken, clientID, command, storagePtr)
- ClientData srvToken; /* Handle on server process passed to
- * Rpc_Reply */
- int clientID; /* Sprite ID of client host */
- int command; /* Command identifier */
- register Rpc_Storage *storagePtr; /* The request fields refer to the
- * request buffers and also indicate
- * the exact amount of data in the
- * request buffers. The reply fields
- * are initialized to NIL for the
- * pointers and 0 for the lengths.
- * This can be passed to Rpc_Reply */
- {
- ReturnStatus status = SUCCESS;
- Proc_PID *pidPtr;
- Rpc_ReplyMem *replyMemPtr;
- Proc_PCBInfo *pcbPtr;
- Proc_ControlBlock *procPtr = (Proc_ControlBlock *) NIL;
- Proc_ControlBlock pcb;
- int *segNumPtr;
- Vm_SegmentInfo *segInfoPtr;
- int *requestPtr;
-
- requestPtr = (int *) storagePtr->requestParamPtr;
- if (*requestPtr == GET_SEG_INFO) {
- segNumPtr = (int *) storagePtr->requestDataPtr;
- segInfoPtr = (Vm_SegmentInfo *) malloc(sizeof (Vm_SegmentInfo));
- status = Vm_EncapSegInfo(*segNumPtr, segInfoPtr);
- storagePtr->replyParamPtr = (Address) segInfoPtr;
- storagePtr->replyParamSize = sizeof(Vm_SegmentInfo);
- goto done;
- } else if (*requestPtr == GET_PCB) {
- pidPtr = (Proc_PID *) storagePtr->requestDataPtr;
- if (*pidPtr >= proc_MaxNumProcesses) {
- status = GEN_INVALID_ARG;
- } else {
- procPtr = Proc_GetPCB(*pidPtr);
- if (procPtr == (Proc_ControlBlock *) NIL) {
- panic("Proc_RpcGetPCB: found nil PCB!");
- status = FAILURE;
- }
- }
- if (status != SUCCESS) {
- Rpc_Reply(srvToken, status, storagePtr,
- (int(*)())NIL, (ClientData)NIL);
- return(SUCCESS);
- }
-
- bcopy((Address) procPtr, (Address) &pcb, sizeof (Proc_ControlBlock));
- TICKS_TO_TIME(pcb);
- pcbPtr = (Proc_PCBInfo *) malloc(sizeof (Proc_PCBInfo));
- storagePtr->replyParamPtr = (Address) pcbPtr;
- storagePtr->replyParamSize = sizeof(Proc_PCBInfo);
- FillPCBInfo(&pcb, pcbPtr);
-
- if (procPtr->argString != (Address) NIL) {
- storagePtr->replyDataSize = strlen(procPtr->argString) + 1;
- storagePtr->replyDataPtr = (Address) malloc(storagePtr->replyDataSize);
- (void) strcpy(storagePtr->replyDataPtr, procPtr->argString);
- } else {
- storagePtr->replyDataSize = 0;
- storagePtr->replyDataPtr = (Address) NIL;
- }
- }
- done:
- replyMemPtr = (Rpc_ReplyMem *) malloc(sizeof(Rpc_ReplyMem));
- replyMemPtr->paramPtr = storagePtr->replyParamPtr;
- replyMemPtr->dataPtr = storagePtr->replyDataPtr;
-
- Rpc_Reply(srvToken, status, storagePtr, Rpc_FreeMem,
- (ClientData) replyMemPtr);
- return(SUCCESS);
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Proc_GetResUsage --
- *
- * Returns the resource usage for a process.
- *
- * Results:
- * SYS_INVALID_ARG - buffer address was invalid.
- * PROC_INVALID_PID - The pid was out-of-range or specified a
- * non-existent process.
- * SYS_ARG_NOACCESS - The buffers to store the pcbs in were not
- * accessible.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- ReturnStatus
- Proc_GetResUsage(pid, bufferPtr)
- Proc_PID pid;
- Proc_ResUsage *bufferPtr;
- {
- register Proc_ControlBlock *procPtr;
- Proc_ResUsage resUsage;
- ReturnStatus status = SUCCESS;
-
- if (pid == PROC_MY_PID) {
- procPtr = Proc_GetEffectiveProc();
- if (procPtr == (Proc_ControlBlock *) NIL) {
- panic("Proc_GetResUsage: procPtr == NIL\n");
- }
- Proc_Lock(procPtr);
- } else {
- procPtr = Proc_LockPID(pid);
- if (procPtr == (Proc_ControlBlock *) NIL) {
- return (PROC_INVALID_PID);
- }
- }
-
- /*
- * Copy the information to the out parameters.
- */
-
- if (bufferPtr == USER_NIL) {
- status = SYS_INVALID_ARG;
- } else {
- Timer_TicksToTime(procPtr->kernelCpuUsage.ticks,
- &resUsage.kernelCpuUsage);
- Timer_TicksToTime(procPtr->userCpuUsage.ticks, &resUsage.userCpuUsage);
- Timer_TicksToTime(procPtr->childKernelCpuUsage.ticks,
- &resUsage.childKernelCpuUsage);
- Timer_TicksToTime(procPtr->childUserCpuUsage.ticks,
- &resUsage.childUserCpuUsage);
- resUsage.numQuantumEnds = procPtr->numQuantumEnds;
- resUsage.numWaitEvents = procPtr->numWaitEvents;
-
- if (Proc_ByteCopy(FALSE, sizeof(Proc_ResUsage),
- (Address) &resUsage, (Address) bufferPtr) != SUCCESS){
- status = SYS_ARG_NOACCESS;
- }
- }
- Proc_Unlock(procPtr);
- return(status);
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Proc_GetPriority --
- *
- * Returns the priority of a process.
- *
- * Results:
- * SYS_INVALID_ARG - priorityPtr address was invalid.
- * PROC_INVALID_PID - The pid was out-of-range or specified a
- * non-existent process.
- * SYS_ARG_NOACCESS - The buffer to store the priority was not
- * accessible.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- ReturnStatus
- Proc_GetPriority(pid, priorityPtr)
- Proc_PID pid; /* ID of process whose priority is to be returned. */
- int *priorityPtr; /* Priority returned by Proc_GetPriority. */
- {
- register Proc_ControlBlock *procPtr;
- ReturnStatus status = SUCCESS;
-
- if (pid == PROC_MY_PID) {
- procPtr = Proc_GetEffectiveProc();
- if (procPtr == (Proc_ControlBlock *) NIL) {
- panic("Proc_GetPriority: procPtr == NIL\n");
- }
- Proc_Lock(procPtr);
- } else {
- procPtr = Proc_LockPID(pid);
- if (procPtr == (Proc_ControlBlock *) NIL) {
- return (PROC_INVALID_PID);
- }
- }
-
- /*
- * Copy the information to the out parameter.
- */
-
- if (priorityPtr == USER_NIL) {
- status = SYS_INVALID_ARG;
- } else {
- if (Proc_ByteCopy(FALSE, sizeof(int),
- (Address) &(procPtr->billingRate),
- (Address) priorityPtr) != SUCCESS) {
- status = SYS_ARG_NOACCESS;
- }
- }
- Proc_Unlock(procPtr);
- return(status);
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Proc_SetPriority --
- *
- * Sets the priority for a process.
- *
- * Results:
- * PROC_INVALID_PID - The pid was out-of-range or specified a
- * non-existent process.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- ReturnStatus
- Proc_SetPriority(pid, priority, useFamily)
- Proc_PID pid; /* ID of process whose priority is to be set. */
- int priority; /* New scheduling priority for pid. */
- Boolean useFamily; /* If TRUE, use pid as the head of a process
- * family, and set the priority of every
- * process in the family. */
- {
- register Proc_ControlBlock *procPtr;
- register Proc_PCBLink *procLinkPtr;
- List_Links *familyList;
- int userID;
- ReturnStatus status;
-
- if (priority > PROC_MAX_PRIORITY) {
- priority = PROC_MAX_PRIORITY;
- } else if (priority < PROC_MIN_PRIORITY) {
- priority = PROC_MIN_PRIORITY;
- }
-
- if (useFamily) {
- /*
- * Set priorities of processes in family.
- */
- status = Proc_LockFamily((int) pid, &familyList, &userID);
- if (status != SUCCESS) {
- return(status);
- }
- if (!Proc_HasPermission(userID)) {
- Proc_UnlockFamily((int) pid);
- return(PROC_UID_MISMATCH);
- }
- LIST_FORALL(familyList, (List_Links *) procLinkPtr) {
- procPtr = procLinkPtr->procPtr;
- Proc_Lock(procPtr);
- procPtr->billingRate = priority;
- Proc_Unlock(procPtr);
- }
- Proc_UnlockFamily((int) pid);
- } else {
- /*
- * Set the individual process's priority.
- */
- if (pid == PROC_MY_PID) {
- procPtr = Proc_GetEffectiveProc();
- Proc_Lock(procPtr);
- } else {
- procPtr = Proc_LockPID(pid);
- if (procPtr == (Proc_ControlBlock *) NIL) {
- return (PROC_INVALID_PID);
- }
- if (!Proc_HasPermission(procPtr->effectiveUserID)) {
- Proc_Unlock(procPtr);
- return(PROC_UID_MISMATCH);
- }
- }
- procPtr->billingRate = priority;
- Proc_Unlock(procPtr);
- }
-
- return(SUCCESS);
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Proc_Profile --
- *
- * Starts profiling the memory accesses of the current process.
- *
- * Results:
- * SUCCESS - always returned for now.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- /*ARGSUSED*/
- ReturnStatus
- Proc_Profile(shiftSize, lowPC, highPC, interval, counterArray)
- int shiftSize; /* # of bits to shift the PC to the right. */
- int lowPC; /* The lowest PC to profile. */
- int highPC; /* The highest PC to profile. */
- Time interval; /* The time interval at which the PC is sampled. */
- int counterArray[]; /* Counters used to count instruction executions. */
- {
- return(SUCCESS);
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Proc_Dump --
- *
- * Prints out an abbreviated proc table for debugging purposes.
- *
- * Results:
- * SUCCESS.
- *
- * Side effects:
- * Prints stuff to screen.
- *
- *
- *----------------------------------------------------------------------
- */
-
- ReturnStatus
- Proc_Dump()
- {
- int i;
- Proc_ControlBlock *pcbPtr;
-
- printf("\n%8s %5s %10s %10s %8s %8s %s\n",
- "ID", "wtd", "user", "kernel", "event", "state", "name");
-
- for (i = 0; i < proc_MaxNumProcesses; i++) {
- pcbPtr = proc_PCBTable[i];
- if (pcbPtr->state != PROC_UNUSED) {
- Proc_DumpPCB(pcbPtr);
- }
- }
- return(SUCCESS);
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Proc_DumpPCB --
- *
- * Prints out the contents of a PCB for debugging purposes.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Prints stuff to the screen.
- *
- *----------------------------------------------------------------------
- */
-
- void
- Proc_DumpPCB(procPtr)
- Proc_ControlBlock *procPtr;
- {
-
- Time kernelTime, userTime;
-
- #define DEBUG_INDEX 0x9
-
- static char *states[] = {
- "unused",
- "running",
- "ready",
- "waiting",
- "exiting",
- "dead",
- "migrated",
- "new",
- "suspended",
- "debug",
- };
- Proc_State state;
-
- state = procPtr->state;
- switch (state) {
- case PROC_UNUSED:
- case PROC_RUNNING:
- case PROC_READY:
- case PROC_WAITING:
- case PROC_EXITING:
- case PROC_DEAD:
- case PROC_MIGRATED:
- case PROC_NEW:
- break;
- case PROC_SUSPENDED:
- /* If process is suspended for debugging print "debug" for its
- * state.
- */
- if (procPtr->genFlags & (PROC_DEBUGGED | PROC_ON_DEBUG_LIST)) {
- state = (Proc_State)DEBUG_INDEX;
- }
- break;
- default:
- printf("Warning: Proc_DumpPCB: process %x has invalid process state: %x.\n",
- procPtr->processID, state);
- return;
- }
- /*
- * A header describing the fields has already been printed.
- */
- Timer_TicksToTime(procPtr->userCpuUsage.ticks, &userTime);
- Timer_TicksToTime(procPtr->kernelCpuUsage.ticks, &kernelTime);
- printf("%8x %5d [%1d,%6d] [%1d,%6d] %8x %8s",
- procPtr->processID,
- procPtr->weightedUsage,
- userTime.seconds,
- userTime.microseconds,
- kernelTime.seconds,
- kernelTime.microseconds,
- procPtr->event,
- states[(int) state]);
- if (procPtr->argString != (Address) NIL) {
- char cmd[30];
- char *space;
-
- (void) strncpy(cmd, procPtr->argString, 30);
- space = strchr(cmd, ' ');
- if (space != (char *) NULL) {
- *space = '\0';
- }
- printf(" %s\n", cmd);
- } else {
- printf("\n");
- }
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * Proc_KillAllProcesses --
- *
- * Send the kill signal to all processes in the proc table except for
- * the caller. If userProcsOnly is TRUE only send signals to user
- * processes.
- *
- * Results:
- * The number of runnable and waiting processes.
- *
- * Side effects:
- * The kill signal bit is set for all processes.
- *
- *----------------------------------------------------------------------
- */
- int
- Proc_KillAllProcesses(userProcsOnly)
- Boolean userProcsOnly; /* TRUE if only kill user processes. */
- {
- register int i;
- register Proc_ControlBlock *pcbPtr;
- Proc_ControlBlock *curProcPtr;
- int alive = 0;
-
- curProcPtr = Proc_GetActualProc();
-
- for (i = 0; i < proc_MaxNumProcesses; i++) {
- pcbPtr = proc_PCBTable[i];
- if (pcbPtr == curProcPtr || pcbPtr->state == PROC_UNUSED ||
- (userProcsOnly && !(pcbPtr->genFlags & PROC_USER))) {
- continue;
- }
- Proc_Lock(pcbPtr);
- if (pcbPtr->state == PROC_RUNNING ||
- pcbPtr->state == PROC_READY ||
- pcbPtr->state == PROC_WAITING ||
- pcbPtr->state == PROC_MIGRATED) {
- alive++;
- (void) Sig_SendProc(pcbPtr, SIG_KILL, 0, (Address)0);
- }
- Proc_Unlock(pcbPtr);
- }
-
- return(alive);
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Proc_WakeupAllProcesses --
- *
- * Wakup all waiting processes.
- *
- * Results:
- * None.
- *
- * Side effects:
- * All waiting processes are awakened.
- *
- *----------------------------------------------------------------------
- */
- void
- Proc_WakeupAllProcesses()
- {
- register int i;
- register Proc_ControlBlock *pcbPtr;
- Proc_ControlBlock *curProcPtr;
-
- curProcPtr = Proc_GetActualProc();
-
- for (i = 0; i < proc_MaxNumProcesses; i++) {
- pcbPtr = proc_PCBTable[i];
- if (pcbPtr == curProcPtr) {
- continue;
- }
- Proc_Lock(pcbPtr);
- if (pcbPtr->state != PROC_UNUSED) {
- Sync_WakeWaitingProcess(pcbPtr);
- }
- Proc_Unlock(pcbPtr);
- }
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Proc_HasPermission --
- *
- * See if the current process has permission to perform an operation on
- * a process with the given user id.
- *
- * Results:
- * TRUE if the current process has the same effective user id
- * as the given user id or the current process is super user.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- Boolean
- Proc_HasPermission(userID)
- int userID;
- {
- Proc_ControlBlock *procPtr;
-
- procPtr = Proc_GetEffectiveProc();
- return(procPtr->effectiveUserID == userID ||
- procPtr->effectiveUserID == PROC_SUPER_USER_ID);
- }
-
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Proc_DoForEveryProc --
- *
- * For every process in the process table, apply *booleanFuncPtr to it.
- * If that returns TRUE, apply *actionFuncPtr to it. This is done by
- * passing booleanFuncPtr to a monitored routine and having it
- * return an array of qualifying processes. There is a bit of a race
- * condition if something happens to any of those processes after the
- * list is returned, but in that case the process is ignored and the next
- * one is processed.
- *
- * IgnoreStatus indicates whether the routine should abort if
- * a non-SUCCESS status is returned by *actionFuncPtr.
- *
- * Results:
- * If anything "unexpected" happens, FAILURE will be returned, but in
- * general SUCCESS is returned. If numMatchedPtr is non-NIL, then
- * the number of processes matched is returned in *numMatchedPtr.
- *
- * Side effects:
- * The process table is locked temporarily. Otherwise, dependent on the
- * call-back procedures.
- *
- *----------------------------------------------------------------------
- */
-
- ReturnStatus
- Proc_DoForEveryProc(booleanFuncPtr, actionFuncPtr, ignoreStatus, numMatchedPtr)
- Boolean (*booleanFuncPtr) _ARGS_((Proc_ControlBlock *pcbPtr));
- /* function to match */
- ReturnStatus (*actionFuncPtr)_ARGS_((Proc_PID pid));
- /* function to invoke on matches */
- Boolean ignoreStatus; /* do not abort if bad ReturnStatus */
- int *numMatchedPtr; /* number of matches in table, or NIL */
- {
- ReturnStatus status = SUCCESS;
- Proc_PID *pidArray;
- int max;
- int i;
- int numMatched;
-
- max = proc_MaxNumProcesses;
-
- pidArray = (Proc_PID *) malloc(sizeof(Proc_PID) * max);
- numMatched = ProcTableMatch(max, booleanFuncPtr, pidArray);
- for (i = 0; i < numMatched; i++) {
- status = (*actionFuncPtr)(pidArray[i]);
- if ((!ignoreStatus) && (status != SUCCESS)) {
- break;
- }
- }
- free((Address) pidArray);
- if (numMatchedPtr != (int *) NIL) {
- *numMatchedPtr = numMatched;
- }
- if (ignoreStatus) {
- return(SUCCESS);
- }
- return(status);
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Proc_SetServerPriority --
- *
- * Changes the priority of a server process to the non-interruptable
- * value. The pid is assumed to be valid.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The process's priority is changed.
- *
- *----------------------------------------------------------------------
- */
-
- void
- Proc_SetServerPriority(pid)
- Proc_PID pid;
- {
- Proc_GetPCB(pid)->billingRate = PROC_NO_INTR_PRIORITY;
- }
-
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Proc_GetHostIDs --
- *
- * Returns the sprite IDs corresponding to the machines on which
- * the current process is effectively executing and on which
- * it is physically executing. These hosts are called the virtualHost
- * and physicalHost, respectively. For an unmigrated process, these
- * two are identical.
- *
- * Results:
- * SUCCESS The call was successful.
- * SYS_ARG_NOACCESS The user arguments were not accessible.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- ReturnStatus
- Proc_GetHostIDs(virtualHostPtr, physicalHostPtr)
- int *virtualHostPtr; /* Buffer to hold virtual host ID. */
- int *physicalHostPtr; /* Buffer to hold physical host ID. */
- {
-
- Proc_ControlBlock *procPtr;
- int host;
-
- if (physicalHostPtr != (int *) USER_NIL) {
-
- if (Vm_CopyOut(sizeof(int), (Address) &rpc_SpriteID,
- (Address) physicalHostPtr) != SUCCESS) {
- return(SYS_ARG_NOACCESS);
- }
- }
-
-
- if (virtualHostPtr != (int *) USER_NIL) {
- procPtr = Proc_GetCurrentProc();
- Proc_Lock(procPtr);
- host = procPtr->peerHostID;
- Proc_Unlock(procPtr);
- if (host == NIL) {
- host = rpc_SpriteID;
- }
- if (Vm_CopyOut(sizeof(int), (Address) &host,
- (Address) virtualHostPtr) != SUCCESS) {
- return(SYS_ARG_NOACCESS);
- }
- }
-
- return(SUCCESS);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * Proc_PushLockStack --
- *
- * Pushes the given lock type on the lock stack for the process.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Stuff is printed if the stack overflows.
- *
- *----------------------------------------------------------------------
- */
-
- /*ARGSUSED*/
- void
- Proc_PushLockStack(pcbPtr, type, lockPtr)
- Proc_ControlBlock *pcbPtr; /* ptr to pcb to modify */
- int type; /* type of lock */
- Address lockPtr; /* ptr to lock */
-
- {
- #ifdef LOCKDEP
- static Boolean firstOverflow = TRUE;
-
- /*
- * Modifying the lock stack of a process has to be an atomic operation,
- * but we don't want to use a lock to do this, since this is part of
- * the code used when locking or unlocking. Using a lock would lead
- * to a circularity and probably a deadlock. All we really need to
- * prevent is an interrupt handler from grabbing a lock while we're
- * modifying the lock stack. A process only modifies its own
- * lock stack, so turning off interrupts should be good enough.
- */
- DISABLE_INTR();
- if (pcbPtr->lockStackSize >= PROC_LOCKSTACK_SIZE) {
- if (firstOverflow) {
- printf("Proc_PushLockStack: stack overflow in pcb 0x%x.\n",pcbPtr);
- firstOverflow = FALSE;
- }
- goto exit;
- }
- if (pcbPtr->lockStackSize < 0 ) {
- printf("Proc_PushLockStack: stack underflow (%d) in pcb 0x%x.\n",
- pcbPtr->lockStackSize, pcbPtr);
- goto exit;
- }
- pcbPtr->lockStack[pcbPtr->lockStackSize].type = type;
- pcbPtr->lockStack[pcbPtr->lockStackSize].lockPtr = lockPtr;
- pcbPtr->lockStackSize++;
- exit:
- ENABLE_INTR();
- #endif
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * Proc_RemoveFromLockStack --
- *
- * Removes the given lock from the stack if it is there.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- /*ARGSUSED*/
- void
- Proc_RemoveFromLockStack(pcbPtr, lockPtr)
- Proc_ControlBlock *pcbPtr; /* ptr to pcb to modify */
- Address lockPtr; /* ptr to lock */
- {
- #ifdef LOCKDEP
- int i;
- int stackTop;
- Boolean found = FALSE;
-
- DISABLE_INTR();
- if (pcbPtr->lockStackSize < 0) {
- ENABLE_INTR();
- panic("Lock stack underflow (1).\n");
- goto exit;
- }
- if (pcbPtr->lockStackSize == 0) {
- goto exit;
- }
- stackTop = pcbPtr->lockStackSize - 1;
- for (i = pcbPtr->lockStackSize - 1; i >= 0; i--) {
- if (pcbPtr->lockStack[i].lockPtr == lockPtr) {
- pcbPtr->lockStack[i].lockPtr = (Address) NIL;
- pcbPtr->lockStack[i].type = -1;
- found = TRUE;
- break;
- }
- }
- if (!found) {
- goto exit;
- }
- for (i = stackTop; i >= 0; i--) {
- if (pcbPtr->lockStack[i].lockPtr != (Address) NIL) {
- break;
- }
- }
- pcbPtr->lockStackSize = i + 1;
- if (pcbPtr->lockStackSize < 0) {
- printf("lockStackSize %d\n",pcbPtr->lockStackSize);
- }
- exit:
- ENABLE_INTR();
- #endif
- }
-
- #ifndef LOCKREG
- #ifndef CLEAN_LOCK
- #ifndef CLEAN
- /*
- *----------------------------------------------------------------------
- *
- * Proc_KDump --
- *
- * Prints out an (kluged) proc table with state information.
- *
- * This routine uses several macros to analyse the event data structure:
- * ISADDR(x) tests if x is a valid address.
- * ISSTR(x) tests if x is a pointer to a valid string.
- * ISALIGN(x) tests if x is an aligned address.
- * ISBOOL(x) tests if x is a boolean.
- * ISSMALL(x) tests is x is a small integer.
- * ISLIST(x) tests if x points to a List_Links structure.
- * ISPCB(x) tests if x points to a Proc_ControlBlock structure.
- * FIELD(x,type,field) is x->type.field
- *
- * Results:
- * SUCCESS.
- *
- * Side effects:
- * Prints stuff to screen.
- *
- *
- *----------------------------------------------------------------------
- */
- #define INT(x) ((int)(x))
- #define INTP(x) ((int *)(x))
- #define ISSTRZ(x) (INT(x)==0 || ISSTR(x))
- #define ISALIGN(x) (ISADDR(x) && (INT(x)&3)==0)
- #define ISALIGNZ(x) (INT(x)==0 || INT(x)==NIL || ISALIGN(x))
- /* sun3 test-and-set sets to 0x80000000, sun4 to 0xff000000 */
- #define ISBOOL(x) (INT(x)==0||INT(x)==1||INT(x)==0x80000000||\
- INT(x)==0xff000000)
- #define ISSMALL(x) (INT(x)>=0&&INT(x)<20)
- #define ISPCBZ(x) (INT(x)==0||INT(x)==NIL||ISPCB(x))
- #define OFF(type,field) (INTP(&(((type *)0)->field))-INTP(0))
- #define READIN(type,src,dst) (READIN_INT(sizeof(type),(Address)(src),\
- (Address)(dst)))
-
- static int ISADDR _ARGS_((Address x));
- static int ISSTR _ARGS_((char *x));
- static int PRINTHANDLE _ARGS_ ((char *str, Fs_HandleHeader *handlePtr));
- static int ISLIST _ARGS_((List_Links *x));
- static int ISPCB _ARGS_((Proc_ControlBlock *x));
- static int FINDPID _ARGS_((Proc_ControlBlock *x));
- static int PRINTRPCCLIENT _ARGS_((RpcClientChannel *x));
- static int PRINTRPCSERVER _ARGS_((RpcServerState *x));
- static int PRINTSERVERPROC _ARGS_((ServerInfo *x));
- static int PRINTLOCK _ARGS_((Sync_Lock *x, int print));
- static int PRINTSEM _ARGS_((Sync_Semaphore *x));
- static int PRINTLFS _ARGS_((Lfs *x, char *text));
-
- /*
- * Read in some memory.
- * The macro looks after the types.
- */
- static int READIN_INT(len,src,dst)
- int len;
- Address src,dst;
- {
- ReturnStatus status;
- int i;
- #if defined(ds3100) || defined(ds5000)
- /* Mach_Probe doesn't work right for some reason */
- char buf[2];
- for (i=0;i<len;i++) {
- if (! Dbg_InRange(((unsigned)src)&~1,2,FALSE)) {
- return FALSE;
- }
- }
- bcopy(src,dst,len);
- return TRUE;
- #else
- for (i=0;i<len;i++) {
- status = Mach_Probe(1,src+i,dst+i);
- if (status != SUCCESS) return FALSE;
- }
- return TRUE;
- #endif
- }
-
- /*
- * Test if x is a valid address.
- */
- static int ISADDR(x)
- Address x;
- {
- int buf;
- if (READIN(int,x,(Address)&buf)) {
- return TRUE;
- } else {
- return FALSE;
- }
- }
-
- /*
- * Test if x is a string. Leave the string in strbuf if so.
- */
- char strbuf[40];
- static int ISSTR(x)
- char *x;
- {
- int i;
- for (i=0;i<sizeof(strbuf);i++) {
- if (!READIN(char,x+i,strbuf+i)) {
- return FALSE;
- }
- if (strbuf[i]=='\0') {
- return TRUE;
- }
- if (!isprint(strbuf[i])) {
- return FALSE;
- }
- }
- strbuf[39]='\0';
- return TRUE;
- }
-
-
- /*
- * Print out the name associated with a handle.
- */
- static int PRINTHANDLE(str,handlePtr)
- char *str;
- Fs_HandleHeader *handlePtr;
- {
- Fs_HandleHeader handle;
- if (!READIN(Fs_HandleHeader,handlePtr,&handle) ||
- !ISLIST(&handle.lruLinks) || !ISBOOL(handle.unlocked.waiting) ||
- !ISSMALL(handle.refCount) ||
- !(handle.lockProcPtr==(Proc_ControlBlock *)NIL ||
- ISPCB(handle.lockProcPtr))) {
- return FALSE;
- }
- if (handle.name==(char *)NIL) {
- printf("%s: \"%s\" (handle locked by %x)", str, "(no name)",
- handle.lockProcPtr);
- } else if (ISSTR(handle.name)) {
- printf("%s: \"%s\" (handle locked by %x)", str, strbuf,
- handle.lockProcPtr);
- } else {
- printf("%s: \"%s\" (handle locked by %x)", str, "(bad name)",
- handle.lockProcPtr);
- }
- return TRUE;
- }
-
- /*
- * Test if x is a list.
- */
- static int ISLIST(x)
- List_Links *x;
- {
- List_Links thisList, prevList, nextList;
- int retVal;
- retVal = READIN(List_Links,x,&thisList) &&
- READIN(List_Links,thisList.prevPtr,&prevList) &&
- READIN(List_Links,thisList.nextPtr,&nextList) &&
- prevList.nextPtr == x && nextList.prevPtr == x;
- return retVal;
- }
-
- /*
- * Test if x is a pcb
- */
- static int ISPCB(x)
- Proc_ControlBlock *x;
- {
- Proc_ControlBlock pcb;
- int retVal;
- retVal = READIN(Proc_ControlBlock,x,&pcb) && ISSMALL(pcb.processor) &&
- ISSTR(pcb.argString) && ISADDR((Address)pcb.links.prevPtr) &&
- ISADDR((Address)pcb.links.nextPtr) && ISSMALL(pcb.state) &&
- ISADDR((Address)pcb.childList) && pcb.processID <=0xfffff;
- #if 0
- if (!retVal) {
- if (!READIN(Proc_ControlBlock,x,&pcb)) {
- printf("PCB: READIN failed ");
- } else if (!ISLIST(&pcb.links)) {
- printf("PCB: LIST failed ");
- } else if (!ISSMALL(pcb.processor)) {
- printf("PCB: SMALL failed ");
- } else if (!ISLIST(&pcb.childListHdr)) {
- printf("PCB: LIST2 failed ");
- } else if (pcb.processID >0xfffff) {
- } else {
- printf("PCB: mystery ");
- }
- }
- #endif
- return retVal;
- }
-
- /*
- * Return PID or 0
- */
- static int FINDPID(x)
- Proc_ControlBlock *x;
- {
- Proc_ControlBlock pcb;
- if (READIN(Proc_ControlBlock,x,&pcb) && ISPCB(&pcb)) {
- return pcb.processID;
- } else {
- return FALSE;
- }
- }
-
- /*
- * Print if x is a rpc client channel
- */
- static int PRINTRPCCLIENT(x)
- RpcClientChannel *x;
- {
- int i;
- RpcClientChannel chan;
- if (!READIN(RpcClientChannel,x,&chan)) {
- return FALSE;
- }
- for (i=0;i<rpcNumChannels;i++) {
- if (rpcChannelPtrPtr[i] == x) {
- printf("RPC client: \"waitCondition\", server %d ",
- chan.serverID);
- if (chan.state & CHAN_FREE) {
- printf("FREE ");
- }
- if (chan.state & CHAN_BUSY) {
- printf("BUSY ");
- }
- if (chan.state & CHAN_WAITING) {
- printf("WAIT ");
- }
- if (chan.state & CHAN_TIMEOUT) {
- printf("TIME ");
- }
- if (chan.state & CHAN_FRAGMENTING) {
- printf("FRAG ");
- }
- return TRUE;
- }
- }
- return FALSE;
- }
-
- /*
- * Test if x is a rpc server.
- */
- static int PRINTRPCSERVER(x)
- RpcServerState *x;
- {
- int i;
- RpcServerState state;
- if (!READIN(RpcServerState,x,&state)) {
- return FALSE;
- }
- for (i=0;i<rpcMaxServers;i++) {
- if (rpcServerPtrPtr[i] == x) {
- printf("RPC server:\"waitCondition\", client %d ",
- state.clientID);
- if (state.state & SRV_NOTREADY) {
- printf("NOTREADY ");
- }
- if (state.state & SRV_FREE) {
- printf("FREE ");
- }
- if (state.state & SRV_BUSY) {
- printf("BUSY ");
- }
- if (state.state & SRV_WAITING) {
- printf("WAIT ");
- }
- if (state.state & SRV_AGING) {
- printf("AGING ");
- }
- if (state.state & SRV_FRAGMENT) {
- printf("FRAG ");
- }
- if (state.state & SRV_NO_REPLY) {
- printf("NO_REPLY ");
- }
- if (state.state & SRV_STUCK) {
- printf("STUCK ");
- }
- return TRUE;
- }
- }
- return FALSE;
- }
-
- /*
- * Print if x is a rpc server proc
- */
- static int PRINTSERVERPROC(x)
- ServerInfo *x;
- {
- int i;
- ServerInfo info;
- if (!READIN(ServerInfo,x,&info)) {
- return FALSE;
- }
- for (i=0;i<proc_NumServers;i++) {
- if (serverInfoTable+i == x) {
- printf("ServerProc: \"condition\" (waiting for task)");
- if (info.flags & SERVER_BUSY) {
- printf("BUSY ");
- }
- if (info.flags & FUNC_PENDING) {
- printf("PENDING ");
- }
- return TRUE;
- }
- }
- return FALSE;
- }
-
- /*
- * Print if x is a Lfs structure
- */
- static int PRINTLFS(x, text)
- Lfs *x;
- char *text;
- {
- Lfs lfs;
- if (!READIN(Lfs,x,&lfs)) {
- return FALSE;
- }
- if (ISSTR(lfs.name) && ISBOOL(lfs.writeBackActive) &&
- PRINTLOCK(&lfs.cacheBackendLock,0) &&
- ISBOOL(lfs.writeBackMoreWork) && ISBOOL(lfs.shutDownActive) &&
- PRINTLOCK(&lfs.lock,0)) {
- (void) ISSTR(lfs.name);
- printf("Lfs: %s on %s", text, strbuf);
- return TRUE;
- }
- return FALSE;
- }
-
- /*
- * Print if x is a lock.
- * Or just return true/false if print=0;
- */
- static int PRINTLOCK(x,print)
- Sync_Lock *x;
- int print;
- {
- Sync_Lock lock;
- if (READIN(Sync_Lock,x,&lock) && ISBOOL(lock.inUse) &&
- ISBOOL(lock.waiting) &&
- ISALIGNZ(lock.holderPC) && ISPCBZ(lock.holderPCBPtr) &&
- ISSTR(lock.name)) {
- if (print) {
- printf("lock \"%s\" at %x", strbuf, lock.holderPC);
- }
- if (print && FINDPID(lock.holderPCBPtr)) {
- printf(" held by process %x", FINDPID(lock.holderPCBPtr));
- }
- return TRUE;
- } else {
- return FALSE;
- }
- }
-
- /*
- * Test if x is a semaphore.
- */
- static int PRINTSEM(x)
- Sync_Semaphore *x;
- {
- Sync_Semaphore sem;
- if (READIN(Sync_Semaphore,x,&sem) && ISSMALL(sem.value) &&
- ISALIGNZ(sem.holderPC) &&
- ISPCBZ(sem.holderPCBPtr) && ISSTR(sem.name)) {
- printf("semaphore \"%s\" at %x", strbuf, sem.holderPC);
- if (FINDPID(sem.holderPCBPtr)) {
- printf(" held by process %x",
- FINDPID(sem.holderPCBPtr));
- }
- return TRUE;
- } else {
- return FALSE;
- }
- }
-
- typedef struct LockEntry {
- int addr; /* Address (event) associated with the lock. */
- char *name; /* Name of the lock event. */
- } LockEntry;
-
- extern Sync_Condition cleanBlockCondition, writeBackComplete,
- closeCondition, lruDone, debugListCondition, familyCondition,
- migrateCondition, evictCondition, recovCondition, recovPingCondition,
- rpcDaemon, freeChannels, signalCondition, codeSegCondition,
- cleanCondition, swapDownCondition, mappingCondition, swapFileCondition;
-
- LockEntry locks[] = {
- (int)&cleanBlockCondition, "cleanBlockCondition",
- (int)&writeBackComplete, "writeBackComplete",
- (int)&closeCondition, "closeCondition",
- (int)&lruDone, "lruDone",
- (int)&debugListCondition, "debugListCondition",
- (int)&familyCondition, "familyCondition",
- (int)&migrateCondition, "migrateCondition",
- (int)&evictCondition, "evictCondition",
- (int)&recovCondition, "recovCondition",
- (int)&rpcDaemon, "rpcDaemon",
- (int)&freeChannels, "freeChannels",
- (int)&signalCondition, "signalCondition (pause syscall)",
- (int)&codeSegCondition, "codeSegCondition",
- (int)&cleanCondition, "cleanCondition",
- (int)&swapDownCondition, "swapDownCondition",
- (int)&mappingCondition, "mappingCondition",
- (int)&swapFileCondition, "swapFileCondition",
- (int)&recovPingCondition, "recovPingCondition",
- 0, 0
- };
-
- static void Proc_KDumpInt _ARGS_((ClientData data, Proc_CallInfo *callInfoPtr));
-
- void
- Proc_KDump(data)
- ClientData data;
- {
- Proc_CallFunc(Proc_KDumpInt, data, 0);
- }
-
- /*ARGSUSED*/
- static void
- Proc_KDumpInt(data, callInfoPtr)
- ClientData data;
- Proc_CallInfo *callInfoPtr;
- {
- int i;
- Proc_ControlBlock *procPtr, *tmpProcPtr;
- int *event;
- int atEvent;
- LockEntry *lockPtr;
- Fscache_FileInfo cacheInfo, *cacheInfoPtr;
- Fs_HandleHeader *handlePtr;
- RpcClientChannel *rpcClientPtr;
- RpcServerState *rpcServerPtr;
- ServerInfo *serverProcPtr;
- Sync_Lock *syncLockPtr;
- Fsconsist_Info consistInfo;
- Lfs *lfsPtr;
- int match;
-
- for (i = 0; i < proc_MaxNumProcesses; i++) {
- procPtr = proc_PCBTable[i];
- match = 0;
- if (procPtr->state == PROC_WAITING) {
- printf("%6x", procPtr->processID);
- if (procPtr->argString != (Address) NIL) {
- char cmd[30];
- char *space;
-
- (void) strncpy(cmd, procPtr->argString, 30);
- space = strchr(cmd, ' ');
- if (space != (char *) NULL) {
- *space = '\0';
- } else {
- cmd[29] = '\0';
- }
- printf("(%s)", cmd);
- }
- printf(": ");
- event = (int *)procPtr->event;
- if (ISADDR((Address)event)) {
- for (lockPtr = locks ; lockPtr->addr != 0; lockPtr++) {
- if ((int)event == lockPtr->addr) {
- printf("condition \"%s\"\n", lockPtr->name);
- goto found;
- }
- }
- if (PRINTLOCK((Sync_Lock *)event,1)) {
- /* Sync_Lock / Sync_KernelLock */
- } else if ((Proc_ControlBlock *)event==procPtr) {
- /* Proc_ControlBlock */
- printf("timer");
- } else if (FINDPID((Proc_ControlBlock *)event)) {
- /* Proc_ControlBlock */
- printf("timer %x", FINDPID((Proc_ControlBlock *)event));
- } else if (PRINTSEM((Sync_Semaphore *)event)) {
- /* Sync_Semaphore */
- } else if (READIN(int,event,&atEvent) && ISBOOL(atEvent)) {
- /* Sync_Condition */
- handlePtr = (Fs_HandleHeader *)
- (event-OFF(Fs_HandleHeader,unlocked));
- if (PRINTHANDLE("handle: \"unlocked\"", handlePtr)) {
- match++;
- }
- /*
- * We might be blocked on the noDirtyBlocks field of
- * a Fscache_FileInfo structure. In that case, print
- * the associated handle.
- */
- if (READIN(Fs_HandleHeader *,((int *)event)-
- OFF(Fscache_FileInfo,noDirtyBlocks)+
- OFF(Fscache_FileInfo,hdrPtr),&handlePtr)) {
- if (PRINTHANDLE("cache block: \"noDirtyBlocks\"",
- handlePtr)) {
- match++;
- }
- }
- /*
- * We might be blocked on the ioDone field of a
- * Fscache_Block structure. In that case, access the
- * cacheInfoPtr and print the handle.
- */
- if (READIN(Fscache_FileInfo *,((int *)event)-
- OFF(Fscache_Block,ioDone)+
- OFF(Fscache_Block,cacheInfoPtr),&cacheInfoPtr)) {
- if (READIN(Fscache_FileInfo,cacheInfoPtr,&cacheInfo) &&
- PRINTHANDLE("cache block: \"ioDone\"",
- cacheInfo.hdrPtr)) {
- match++;
- }
- }
- /*
- * We might be blocked on the waitCondition in the PCB.
- */
- tmpProcPtr = (Proc_ControlBlock *)
- (event-OFF(Proc_ControlBlock,waitCondition));
- if (tmpProcPtr == procPtr) {
- printf("PCB: \"waitCondition\" (wait syscall) ");
- match++;
- } else if (FINDPID(tmpProcPtr)) {
- printf("PCB: \"waitCondition\" %x (wait syscall) ",
- FINDPID(tmpProcPtr));
- match++;
- }
- /* Or we might be blocked on the lockedCondition */
- tmpProcPtr = (Proc_ControlBlock *)
- (event-OFF(Proc_ControlBlock,lockedCondition));
- if (tmpProcPtr==procPtr) {
- printf("PCB: \"lockedCondition\" (locked entry) ");
- match++;
- } else if (FINDPID(tmpProcPtr)) {
- printf("PCB: \"lockedCondition\" %x (locked entry) ",
- FINDPID(tmpProcPtr));
- match++;
- }
- /* Or we might be blocked on Fsconsist_Info */
- syncLockPtr = (Sync_Lock *)(event-
- OFF(Fsconsist_Info,consistDone));
- if (PRINTLOCK(syncLockPtr,1)) {
- printf(" (consistDone)\n");
- match++;
- if (READIN(Fsconsist_Info,syncLockPtr,&consistInfo)) {
- (void) PRINTHANDLE("handle:", consistInfo.hdrPtr);
- }
- }
- syncLockPtr = (Sync_Lock *)(event-
- OFF(Fsconsist_Info,repliesIn));
- if (PRINTLOCK(syncLockPtr,1)) {
- printf(" (repliesIn)\n");
- match++;
- if (READIN(Fsconsist_Info,syncLockPtr,&consistInfo)) {
- (void) PRINTHANDLE("handle:", consistInfo.hdrPtr);
- }
- }
-
- /* Maybe it's a LFS structure */
- lfsPtr = (Lfs *)(event-OFF(Lfs, writeWait));
- if (PRINTLFS(lfsPtr, "writeWait")) {
- match++;
- }
- lfsPtr = (Lfs *)(event-OFF(Lfs, cleanSegmentsWait));
- if (PRINTLFS(lfsPtr, "cleanSegmentsWait")) {
- match++;
- }
- lfsPtr = (Lfs *)(event-OFF(Lfs, cacheBackendLock));
- if (PRINTLFS(lfsPtr, "cacheBackendLock")) {
- match++;
- }
- lfsPtr = (Lfs *)(event-OFF(Lfs, lock));
- if (PRINTLFS(lfsPtr, "Lfs master lock")) {
- match++;
- }
- lfsPtr = (Lfs *)(event-OFF(Lfs, checkPointWait));
- if (PRINTLFS(lfsPtr, "checkPointWait")) {
- match++;
- }
-
- /* Or maybe something else. */
- serverProcPtr = (ServerInfo *)(event-
- OFF(ServerInfo, condition));
- if (PRINTSERVERPROC(serverProcPtr)) {
- match++;
- }
- rpcClientPtr = (RpcClientChannel *)(event-
- OFF(RpcClientChannel, waitCondition));
- if (PRINTRPCCLIENT(rpcClientPtr)) {
- match++;
- }
- rpcServerPtr = (RpcServerState *)(event-
- OFF(RpcServerState, waitCondition));
- if (PRINTRPCSERVER(rpcServerPtr)) {
- match++;
- }
- handlePtr = (Fs_HandleHeader *)(event-OFF(Fsrmt_IOHandle,
- recovery.reopenComplete));
- if (PRINTHANDLE("\"recovery.reopenComplete\"", handlePtr)) {
- match++;
- }
- if (!match) {
- printf("condition %x", (int)event);
- } else if (match>1) {
- printf("(Ambiguous)");
- }
- } else {
- printf("event %x", (int)event);
- }
- } else if ((int)event == -1) {
- printf("wakeup signal (prob. select syscall)");
- } else {
- printf("event? %x", (int)event);
- }
- printf("\n");
- found:;
- }
- }
- }
- #define KDUMP
- #endif
- #endif
- #endif
-
- #ifndef KDUMP
- /* ARGSUSED */
- ReturnStatus
- Proc_KDump(dummy)
- ClientData dummy;
- {
- return SUCCESS;
- }
- #endif
-